<template>
  <canvas ref="container" class="w-full h-full"></canvas>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { WebGPU } from "../../lib/webgpu/WebGPU";

const container = ref(null);
const webgpu = new WebGPU();

const triangle = {
  vertex: new Float32Array([0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]),
  vertexCount: 3,
};

async function initPipeline(device, format) {
  let pipeline = await device.createRenderPipelineAsync({
    layout: "auto",
    vertex: {
      module: device.createShaderModule({
        code: `
            struct VertexOutput {
              @builtin(position) Position : vec4<f32>,
              @location(0) fragPosition: vec4<f32>
            };
  
            @vertex
            fn main(
              @location(0) position : vec3<f32>,
            ) -> VertexOutput {
              var output : VertexOutput;
              output.Position = vec4<f32>(position, 1.0);
              output.fragPosition = (output.Position + vec4<f32>(1.0, 1.0, 1.0, 1.0)) * 0.5;
              return output;
            }
          `,
      }),
      entryPoint: "main",
      buffers: [
        {
          arrayStride: 3 * 4,
          attributes: [
            {
              shaderLocation: 0,
              offset: 0,
              format: "float32x3",
            },
          ],
        },
      ],
    },
    fragment: {
      module: device.createShaderModule({
        code: `
            @fragment
            fn main(
              @location(0) fragPosition: vec4<f32>,
            ) -> @location(0) vec4<f32> {
                return fragPosition;
            }
          `,
      }),
      entryPoint: "main",
      targets: [
        {
          format: format,
        },
      ],
    },
    primitive: {
      topology: "triangle-list",
    },
  });

  let vertexBuffer = device.createBuffer({
    label: "GPUBuffer store vertex",
    size: triangle.vertex.byteLength,
    // eslint-disable-next-line no-undef
    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
  });
  device.queue.writeBuffer(vertexBuffer, 0, triangle.vertex);

  return { pipeline, vertexBuffer };
}

function draw(device, context, pipelineObj) {
  let commandEncoder = device.createCommandEncoder();
  let renderPassDescriptor = {
    colorAttachments: [
      {
        view: context.getCurrentTexture().createView(),
        clearValue: {
          r: 0.0,
          g: 0.0,
          b: 0.0,
          a: 1.0,
        },
        loadOp: "clear",
        storeOp: "store",
      },
    ],
  };
  let passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
  passEncoder.setPipeline(pipelineObj.pipeline);
  passEncoder.setVertexBuffer(0, pipelineObj.vertexBuffer);
  passEncoder.draw(triangle.vertexCount);
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
}

async function init() {
  let canvas = container.value;
  let { device, context, format } = await webgpu.initWebGPU(canvas);
  let pipelineObj = await initPipeline(device, format);
  draw(device, context, pipelineObj);

  window.addEventListener("resize", () => {
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    draw(device, context, pipelineObj);
  });
}

onMounted(() => {
  init();
});
</script>
